package indexer;

import interfacemanagement.Receptor;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import utils.PhysicalFileManaging;

/**
 * Lists, recursively, the files of a specific directory, and processes them depending on
 * the extension of each file, passing the files to the specific implemented
 * file-processor
 * @author Mauricio Silclir
 */
public class DirectoryManager extends Thread {
	private String initialDirectory;
	private boolean active;
	private Receptor receptor;
	private String lastPath;
	private PhysicalFileManaging physicalFileManager;
	private FileManager fileManager;
	private int currentDirNumber;

	public DirectoryManager() {
	}

	public DirectoryManager(String initialDirectory, Receptor receptor) throws ClassNotFoundException, IOException {
		this.initialDirectory = initialDirectory;
		this.receptor = receptor;
		lastPath = this.initialDirectory;
		physicalFileManager = new PhysicalFileManaging();
		fileManager = new FileManager();
	}

	/**
	 * Initialize the DirectoryManager with a fileCollection provided by a external object
	 * (i.e: read from a file)
	 * @param initialDirectory
	 * @param receptor
	 * @param fileCollections
	 */
	public DirectoryManager(String initialDirectory, Receptor receptor, ArrayList<File> currentFiles) {
		this.initialDirectory = initialDirectory;
		this.receptor = receptor;
		this.lastPath = this.initialDirectory;
		physicalFileManager = new PhysicalFileManaging();
	}

	/**
	 * Initiates the processing of the initial directory, to obtain all the files contained
	 * in it.
	 */
	public void run() {
		this.active = true;
		if (this.initialDirectory != null) {
			File dir = new File(this.initialDirectory);
			if (dir.isDirectory()) {
				physicalFileManager.add(dir);
				receptor.setTotal(countDirectories(dir));
			}
		}
		try {
			listarArchivos();
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
		receptor.notifyFinalization();
	}

	private long countDirectories(File baseDir) {
		long count = 1;
		for (File file : baseDir.listFiles()) {
			if (file.isDirectory()) {
				count += countDirectories(file);
			}
		}
		return count;
	}
	/**
	 * Lists, recursively, the files contained in a specific directory, and passes them to
	 * the specific implemented file-processor, depending on the extension of each file
	 * @param path, the path of the directory from which will be obtained the list of files
	 * to process
	 * @throws ClassNotFoundException 
	 */
	private void listarArchivos() throws ClassNotFoundException, IOException {
		if (!isActive())
			return;
		orderFiles();
		if (physicalFileManager.getNumberOfDirectoryRegisters() > 0)
			listarArchivos();
	}

	/**
	 * Obtains the list of files from the last directory in the array, and save them into
	 * collections to process the files. Once processed, the actual directory is removed
	 * from the list, in order to avoid duplicated processing of the same directory
	 * @throws ClassNotFoundException 
	 */
	private void orderFiles() throws ClassNotFoundException, IOException {
		currentDirNumber ++;
		File nextDirectory = physicalFileManager.getNextDirectory();
		File[] listOfFiles = nextDirectory.listFiles();
		ArrayList<File> directories = new ArrayList<File>();
		ArrayList<File> files = new ArrayList<File>();
		if (listOfFiles != null) {
			for (File thisFile : listOfFiles) {
				if (thisFile.isDirectory()) {
					directories.add(thisFile);
				} else {
					files.add(thisFile);
				}
			}
			physicalFileManager.add(directories);
			if (files.size() > 0) {
				physicalFileManager.add(files);
			}
			// tomar total de dirs y total de archivos
			processFiles(files);
			physicalFileManager.deleteDirectory(nextDirectory);
		}
	}

	private void processFiles(ArrayList<File> files) throws ClassNotFoundException, IOException {
		
		for (int i = 0; i < files.size(); i++) {
			File file = files.get(i);
			fileManager.processFile(file);
			receptor.notifyAdvance(currentDirNumber, (i + 1), files.size());
			physicalFileManager.deleteFile(file);
		}
		fileManager.setNumberOfDocuments();
	}

	public String getDirectorioInicial() {
		return initialDirectory;
	}

	public void setDirectorioInicial(String directorioInicial) {
		this.initialDirectory = directorioInicial;
	}

	public boolean isActive() {
		return active;
	}

	public synchronized void setActive(boolean active) {
		this.active = active;
	}

	public String getLastPath() {
		return lastPath;
	}
}
